package com.dragons.dragonsvf.utils.secret;
import com.dragons.dragonsvf.utils.idbuilder.IdUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Arrays;
import java.util.Base64;

/**
 * @author Dragons.G
 * @date 2025-05-05 20:12:42
 * @description SM4工具类（固定密钥版）
 */
public class FixedSM4Util {

    public static void main(String[] args) throws Exception {
//        // 示例密钥 和 IV
//        String key = "b7b3gSMFWd9a67i1"; // 16字符ASCII密钥
//        String iv = "LlFe66u15Md8Ycg1";   // 16字符ASCII IV
//        // 测试ECB模式
//        String plainText = "Hello SM4!";
//        String encryptedECB = encryptECB(plainText, key);
//        String decryptedECB = decryptECB(encryptedECB, key);
//        System.out.println("ECB模式测试:");
//        System.out.println("加密结果: " + encryptedECB);
//        System.out.println("解密结果: " + decryptedECB);
//        // 测试CBC模式
//        String encryptedCBC = encryptCBC(plainText, key, iv);
//        String decryptedCBC = decryptCBC(encryptedCBC, key, iv);
//        System.out.println("\nCBC模式测试:");
//        System.out.println("加密结果: " + encryptedCBC);
//        System.out.println("解密结果: " + decryptedCBC);

        // 下面是没有秘钥和IV的
        // 测试ECB模式
        String plainText = "yangnan666.";
//        String encryptedECB = encryptNoneKeyIvECB(plainText);
//        String decryptedECB = decryptNoneKeyIvECB(encryptedECB);
//        System.out.println("NoneKeyIvECB模式测试:");
//        System.out.println("NoneKeyIvECB加密结果: " + encryptedECB);
//        System.out.println("NoneKeyIvECB解密结果: " + decryptedECB);
//        // 测试CBC模式
        String encryptedCBC = encryptNoneKeyIvCBC(plainText);
        String decryptedCBC = decryptNoneKeyIvCBC(encryptedCBC);
        System.out.println("NoneKeyIvCBC模式测试:\n");

        System.out.println("NoneKeyIvCBC加密结果: " + encryptedCBC);
        System.out.println("NoneKeyIvCBC解密结果: " + decryptedCBC);

//        String uuid = IdUtil.uuid(32);
//        System.out.println(uuid);
    }


    private static final String KEY = "DRAGONSGALYSON13";
    private static final String IV  = "DRAGONSGALYSON13";
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    // 密钥强制截断为16字节
    private static byte[] processKey(String keyStr) {
        byte[] keyBytes = keyStr.getBytes(StandardCharsets.UTF_8);
        return Arrays.copyOf(keyBytes, 16);
    }

    /** ECB模式加密 */
    public static String encryptECB(String plainText, String key) throws Exception {
        byte[] keyBytes = processKey(key);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");
        Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /** CBC模式加密 */
    public static String encryptCBC(String plainText, String key, String ivStr) throws Exception {
        byte[] keyBytes = processKey(key);
        byte[] ivBytes = processKey(ivStr); // IV同样需要16字节
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /** ECB模式解密 */
    public static String decryptECB(String cipherText, String key) throws Exception {
        byte[] keyBytes = processKey(key);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");

        Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding", "BC");
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(cipherText));
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    /** CBC模式解密  */
    public static String decryptCBC(String cipherText, String key, String ivStr) throws Exception {
        byte[] keyBytes = processKey(key);
        byte[] ivBytes = processKey(ivStr);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(cipherText));
        return new String(decrypted, StandardCharsets.UTF_8);
    }










    /** ECB模式加密 */
    public static String encryptNoneKeyIvECB(String plainText) throws Exception {
        byte[] keyBytes = processKey(KEY);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");
        Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /** CBC模式加密 */
    public static String encryptNoneKeyIvCBC(String plainText) throws Exception {
        byte[] keyBytes = processKey(KEY);
        byte[] ivBytes = processKey(IV); // IV同样需要16字节
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }
    /** ECB模式解密 */
    public static String decryptNoneKeyIvECB(String cipherText) throws Exception {
        byte[] keyBytes = processKey(KEY);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");
        Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding", "BC");
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(cipherText));
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    /** CBC模式解密  */
    public static String decryptNoneKeyIvCBC(String cipherText) {
        byte[] keyBytes = processKey(KEY);
        byte[] ivBytes = processKey(IV);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        byte[] decrypted = new byte[0];
        try {
            Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            decrypted = cipher.doFinal(Base64.getDecoder().decode(cipherText));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return new String(decrypted, StandardCharsets.UTF_8);
    }



}
